// feishu/feishu_stream_notifier.go
package feishu

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"

	"v2/config"
	"v2/model"
	"v2/templates_card"
	"v2/util"
)

// FeiShuStreamNotifier 飞书 Stream 告警通知器
type FeiShuStreamNotifier struct {
	CardRenderer  *templates_card.AlertCardRenderer
	PhoneNumbers  []string
	ReceiveIDType string
	TokenURL      string
	BatchGetIDURL string
	MsgURL        string
	AppID         string // 保存 AppID
	AppSecret     string // 保存 AppSecret
}

// NewFeiShuStreamNotifier 创建飞书 Stream 通知器
func NewFeiShuStreamNotifier(appID, appSecret, receiveIDType string, phoneNumbers []string) *FeiShuStreamNotifier {
	return &FeiShuStreamNotifier{
		CardRenderer:  templates_card.NewAlertCardRenderer(),
		PhoneNumbers:  phoneNumbers,
		ReceiveIDType: receiveIDType,
		TokenURL:      "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
		BatchGetIDURL: "https://open.feishu.cn/open-apis/contact/v3/users/batch_get_id",
		MsgURL:        "https://open.feishu.cn/open-apis/im/v1/messages",
		AppID:         appID,     // 保存 AppID
		AppSecret:     appSecret, // 保存 AppSecret
	}
}

// getTenantToken 获取 tenant_access_token
func (f *FeiShuStreamNotifier) getTenantToken() (string, error) {
	log.Printf("[FeiShuStream] 开始获取 token")

	// 构建请求体
	payload := map[string]string{
		"app_id":     f.AppID,
		"app_secret": f.AppSecret,
	}

	jsonData, err := json.Marshal(payload)
	if err != nil {
		log.Printf("[FeiShuStream] JSON序列化失败: %v", err)
		return "", err
	}

	// 创建带超时的HTTP客户端
	client := &http.Client{
		Timeout: 10 * time.Second,
	}

	resp, err := client.Post(f.TokenURL, "application/json", bytes.NewReader(jsonData))
	if err != nil {
		log.Printf("[FeiShuStream] HTTP请求失败: %v", err)
		return "", fmt.Errorf("网络请求失败: %v", err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	log.Printf("[FeiShuStream] API响应状态码: %d", resp.StatusCode)
	log.Printf("[FeiShuStream] API响应: %s", string(body))

	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		log.Printf("[FeiShuStream] 响应解析失败: %v", err)
		return "", fmt.Errorf("响应解析失败: %v", err)
	}

	// 检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		msg, _ := result["msg"].(string)
		if msg == "" {
			msg = "HTTP请求失败"
		}
		log.Printf("[FeiShuStream] HTTP请求失败: 状态码 %d, 消息 %s", resp.StatusCode, msg)
		return "", fmt.Errorf("HTTP请求失败: 状态码 %d, 消息 %s", resp.StatusCode, msg)
	}

	// 处理code字段
	code, codeOk := result["code"].(float64)
	if !codeOk {
		// 尝试其他可能的类型
		if codeInt, ok := result["code"].(int); ok {
			code = float64(codeInt)
			codeOk = true
		} else if codeStr, ok := result["code"].(string); ok {
			if c, err := strconv.ParseFloat(codeStr, 64); err == nil {
				code = c
				codeOk = true
			}
		}
	}

	// 判断成功响应
	if codeOk && code != 0 {
		msg, _ := result["msg"].(string)
		log.Printf("[FeiShuStream] 业务错误: code=%v, msg=%s", code, msg)
		return "", fmt.Errorf("业务错误: code=%v, msg=%s", code, msg)
	}

	// 获取token
	token, tokenOk := result["tenant_access_token"].(string)
	if !tokenOk || token == "" {
		// 尝试其他可能的字段名
		if token, ok := result["app_access_token"].(string); ok && token != "" {
			log.Printf("[FeiShuStream] 使用 app_access_token 代替 tenant_access_token")
			return token, nil
		}

		log.Printf("[FeiShuStream] 响应中缺少有效的 tenant_access_token")
		return "", fmt.Errorf("响应中缺少有效的 tenant_access_token")
	}

	log.Printf("[FeiShuStream] 成功获取 token")
	return token, nil
}

// GetUserIDByMobile 通过手机号获取用户ID
func (f *FeiShuStreamNotifier) GetUserIDByMobile(token, mobile string) (string, error) {
	// 格式化手机号（添加国家代码）
	if !strings.HasPrefix(mobile, "+") {
		mobile = "+86 " + mobile
	}

	// 确保手机号格式正确（+86 后面有空格）
	if strings.HasPrefix(mobile, "+86") && !strings.HasPrefix(mobile, "+86 ") {
		mobile = "+86 " + strings.TrimPrefix(mobile, "+86")
	}

	log.Printf("[FeiShuStream] 正在查询手机号: %s", mobile)

	// 构建请求体
	requestBody := map[string]interface{}{
		"mobiles":          []string{mobile},
		"user_id_type":     f.ReceiveIDType,
		"include_resigned": false,
	}

	jsonData, err := json.Marshal(requestBody)
	if err != nil {
		return "", err
	}

	// 创建POST请求
	req, err := http.NewRequest("POST", f.BatchGetIDURL, bytes.NewReader(jsonData))
	if err != nil {
		return "", err
	}

	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("Content-Type", "application/json; charset=utf-8")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	log.Printf("[FeiShuStream] API响应: %s", string(body))

	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		return "", err
	}

	// 只有当code存在且不等于0时才返回错误
	if code, ok := result["code"].(float64); ok && code != 0 {
		msg := "未知错误"
		if m, ok := result["msg"].(string); ok {
			msg = m
		}
		return "", fmt.Errorf("获取用户ID失败: %s", msg)
	}

	// 更健壮地解析响应
	data, ok := result["data"].(map[string]interface{})
	if !ok {
		return "", fmt.Errorf("解析用户数据失败: 无效的数据格式")
	}

	items, ok := data["user_list"].([]interface{})
	if !ok || len(items) == 0 {
		return "", fmt.Errorf("未找到有效的用户ID")
	}

	// 获取第一个用户的信息
	userInfo, ok := items[0].(map[string]interface{})
	if !ok {
		return "", fmt.Errorf("解析用户信息失败")
	}

	// 获取用户ID
	userID, ok := userInfo["user_id"].(string)
	if !ok {
		return "", fmt.Errorf("获取用户ID失败: 用户ID字段不存在或类型错误")
	}

	return userID, nil
}

// GetUserIDByPhoneNumbers 通过配置的手机号列表获取所有用户ID
func (f *FeiShuStreamNotifier) GetUserIDByPhoneNumbers() ([]string, error) {
	// 1. 获取 tenant_access_token
	token, err := f.getTenantToken()
	if err != nil {
		return nil, fmt.Errorf("获取 token 失败: %v", err)
	}

	var userIds []string

	for _, mobile := range f.PhoneNumbers {
		log.Printf("[FeiShuStream] 正在处理手机号: %s", mobile)

		// 格式化手机号
		formattedMobile := mobile
		if !strings.HasPrefix(mobile, "+") {
			formattedMobile = "+86 " + mobile
		}

		log.Printf("[FeiShuStream] 格式化后的手机号: %s", formattedMobile)

		// 获取用户ID
		userID, err := f.GetUserIDByMobile(token, formattedMobile)
		if err != nil {
			log.Printf("[FeiShuStream] 获取手机号 %s 的用户ID失败: %v", formattedMobile, err)
			continue
		}

		log.Printf("[FeiShuStream] 手机号 %s 对应的用户ID: %s", formattedMobile, userID)
		userIds = append(userIds, userID)
	}

	return userIds, nil
}

// SendAlertCard 发送告警卡片

func (f *FeiShuStreamNotifier) SendAlertCard(alert model.AlertInfo) error {
	log.Printf("[FeiShuStream] 开始发送告警卡片，告警ID: %s, 规则名: %s", alert.ID, alert.RuleName)
	log.Printf("[FeiShuStream] 告警详情: %+v", alert)

	// 渲染卡片前添加日志
	log.Printf("[FeiShuStream] 卡片渲染前 - 规则名: %s, 级别: %s", alert.RuleName, alert.SeverityText)

	// 1. 渲染告警卡片
	cardContent, err := f.CardRenderer.RenderAlertCard(alert)
	if err != nil {
		log.Printf("[FeiShuStream] 渲染卡片失败: %v", err)
		return err
	}

	log.Printf("[FeiShuStream] 渲染的卡片内容: %s", string(cardContent))

	// 2. 获取 tenant_access_token
	token, err := f.getTenantToken()
	if err != nil {
		return fmt.Errorf("获取 token 失败: %v", err)
	}

	var receiveIDs []string

	// 3. 根据 ReceiveIDType 确定接收者
	if f.ReceiveIDType == "chat_id" {
		// 如果是 chat_id 类型，直接使用配置的 chat_ids
		receiveIDs = config.Global.Notifier.FeiShuStream.ChatIDs
		log.Printf("[FeiShuStream] 使用配置的群聊ID: %v", receiveIDs)

		if len(receiveIDs) == 0 {
			return fmt.Errorf("配置了 chat_id 类型，但 chat_ids 为空")
		}
	} else {
		// 否则，通过手机号获取用户ID列表
		receiveIDs, err = f.GetUserIDByPhoneNumbers()
		if err != nil {
			log.Printf("[FeiShuStream] 通过手机号获取用户ID失败: %v", err)
			return err
		}

		if len(receiveIDs) == 0 {
			log.Printf("[FeiShuStream] 没有有效的用户ID，跳过发送")
			return nil
		}
	}

	// 4. 构建原始变量（用于存储到 Redis）
	log.Printf("[FeiShuStream] 🚀 准备构建告警变量，告警ID: %s", alert.ID)

	variables := map[string]string{
		"rule_name":      alert.RuleName,
		"cluster":        alert.Cluster,
		"severity":       strconv.Itoa(alert.Severity),
		"prom_ql":        alert.PromQl,
		"trigger_time":   strconv.FormatInt(alert.TriggerTime, 10),
		"trigger_value":  alert.TriggerValue,
		"alert_level":    alert.SeverityText,
		"cate":           alert.Cate,
		"formatted_time": alert.FormattedTime,
		"group_id":       strconv.Itoa(alert.GroupID),
		"group_name":     alert.GroupName,
		"datasource_id":  strconv.Itoa(alert.DatasourceID),
		"tags":           f.CardRenderer.FormatTags(alert.TagsMap),
		"alert_id":       alert.ID,
		"time":           alert.FormattedTime, // 确保与 handleCompleteAlert 中使用的 key 一致
	}

	// 转换为 interface{} 类型
	interfaceVariables := make(map[string]interface{})
	for k, v := range variables {
		interfaceVariables[k] = v
		log.Printf("[FeiShuStream] 📦 变量: %s = %v", k, v)
	}

	// 5. 尝试保存到 Redis
	log.Printf("[FeiShuStream] 💾 尝试保存告警变量到 Redis，告警ID: %s", alert.ID)
	if err := util.SaveAlertVariables(alert.ID, interfaceVariables); err != nil {
		log.Printf("[FeiShuStream] ⚠️ 保存告警变量到 Redis 失败: %v", err)
		// 不返回错误，因为即使保存失败，卡片仍应发送
	} else {
		log.Printf("[FeiShuStream] ✅ 成功保存告警变量到 Redis，告警ID: %s", alert.ID)
	}

	// 4. 遍历所有接收者，发送卡片
	var successCount, failureCount int
	for _, receiveID := range receiveIDs {
		err := f.sendCardToUser(receiveID, cardContent, token)
		if err != nil {
			log.Printf("[FeiShuStream] 发送给 %s 失败: %v", receiveID, err)
			failureCount++
		} else {
			successCount++
		}
	}

	// 5. 记录日志
	total := len(receiveIDs)
	log.Printf("[FeiShuStream] 告警卡片已发送: %s, 成功: %d/%d", alert.RuleName, successCount, total)

	if failureCount > 0 {
		return fmt.Errorf("部分消息发送失败: %d/%d", failureCount, total)
	}

	return nil
}

// sendCardToUser 发送卡片消息给单个用户
func (f *FeiShuStreamNotifier) sendCardToUser(receiveID string, cardContent []byte, token string) error {
	// 1. 构造请求体
	payload := map[string]interface{}{
		"receive_id": receiveID,
		"msg_type":   "interactive",
		"content":    string(cardContent),
	}

	// 2. 序列化整个payload
	jsonData, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("请求体序列化失败: %v", err)
	}

	// 3. 创建请求
	url := fmt.Sprintf("%s?receive_id_type=%s", f.MsgURL, f.ReceiveIDType)
	req, err := http.NewRequest("POST", url, bytes.NewReader(jsonData))
	if err != nil {
		return fmt.Errorf("创建请求失败: %v", err)
	}

	req.Header.Set("Content-Type", "application/json; charset=utf-8")
	req.Header.Set("Authorization", "Bearer "+token)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("发送请求失败: %v", err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	var result map[string]interface{}
	json.Unmarshal(body, &result)

	// 4. 检查响应
	var code float64
	if codeVal, ok := result["code"]; ok {
		switch v := codeVal.(type) {
		case float64:
			code = v
		case int:
			code = float64(v)
		case string:
			if c, err := strconv.ParseFloat(v, 64); err == nil {
				code = c
			}
		}
	}

	if code != 0 {
		msg, _ := result["msg"].(string)
		return fmt.Errorf("发送消息失败: %s", msg)
	}

	log.Printf("[FeiShuStream] 告警卡片已成功发送给 %s", receiveID)
	return nil
}
